package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.article.ArticleConstants;
import com.heima.common.exception.CustException;
import com.heima.feigns.AdminFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Transactional
public class HotArticleServiceImpl implements HotArticleService {
    @Autowired
    private ApArticleMapper apArticleMapper;

    /**
     * 计算热文章
     */
    @Override
    public void computeHotArticle() {
        //1.获取最近五天发布的文章
        String dateParam = LocalDateTime.now().minusDays(5).format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
        List<ApArticle> articleList = apArticleMapper.selectArticleByDate(dateParam);
        if (CollectionUtils.isEmpty(articleList)) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2.计算热点文章分值
        List<HotArticleVo> hotArticleVoList = computeArticleScore(articleList);
        //3 为每一个频道缓存热点较高的30条文章
        cacheTagToRedis(hotArticleVoList);
    }

    /**
     * 计算热点文章的分值
     *
     * @param articleList
     * @return
     */
    private List<HotArticleVo> computeArticleScore(List<ApArticle> articleList) {
        List<HotArticleVo> hotArticleVoList = articleList.stream().map(apArticle -> {
            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(apArticle, hotArticleVo);
            //计算文章得分
            Integer score = computeScore(apArticle);
            hotArticleVo.setScore(score);
            return hotArticleVo;
        }).collect(Collectors.toList());
        return hotArticleVoList;
    }

    private Integer computeScore(ApArticle apArticle) {
        int score = 0;
        // 阅读1
        if (apArticle.getViews()!=null) {
            score += apArticle.getViews() * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }
        // 点赞 3
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        // 评论 5
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        // 收藏 8
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }
    /**
     * 频道缓存热点较高的30条文章
     * @param hotArticleVoList
     */
    @Autowired
    AdminFeign adminFeign;
    private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) {
        //1.获取所有的频道信息
        ResponseResult<List<AdChannel>> result = adminFeign.selectAllChannel();
        if (result.getCode()!=0&&result.getData()==null) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        List<AdChannel> channelList = result.getData();
        //2.遍历所有的频道  为每个频道缓存相应的文章
        channelList.forEach(channel->{
            // 过滤热点频道id = 当前channel id     排序 得分降序   截取前三十条文章
            List<HotArticleVo> articleVoList = hotArticleVoList.stream().filter(hotArticleVo -> hotArticleVo.getChannelId().equals(channel.getId()))
                    .sorted(Comparator.comparing(HotArticleVo::getScore).reversed())
                    .limit(30)
                    .collect(Collectors.toList());
            cacheToRedis(articleVoList,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+channel.getId());
        });
        //3.为推荐频道缓存30条文章
        List<HotArticleVo> hotArticleByDefault = hotArticleVoList.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(30).collect(Collectors.toList());
        cacheToRedis(hotArticleByDefault,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);
    }

    /**
     *
     * @param hotArticleVoList  要缓存的文章列表
     * @param cacheKey      缓存到redis中的key
     */
    @Autowired
    RedisTemplate<String,String> redisTemplate;
    private void cacheToRedis(List<HotArticleVo> hotArticleVoList, String cacheKey) {
        redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(hotArticleVoList));
    }
}

